#ifndef FLOAT_VOL_GRID_H
#define FLOAT_VOL_GRID_H

#include "RawVolGrid.h"
#include "matrix.h"
#include "OglViewInterfaces.h"

class FloatVolGrid // interface
{
public:
	virtual int GetDataBounds(int) const=0;
	virtual mdsVector<2, double> GetSpaceBounds(int) const=0;
	virtual float GetValAt(int, int, int) const = 0;
	virtual float GetValAt(double, double, double) const=0;
	virtual void SetValAt(int, int, int, float) = 0;
	virtual mdsVector<3, double> EvalGradientAt(double, double, double) const=0;

	virtual double FvgGetMin() const=0;
	virtual double FvgGetMax() const=0;

	virtual double FvgGetMean() const=0;
	virtual double FvgGetStdDev() const=0;
	virtual double FvgGetMeanSqrd() const=0;

};

class FloatVolGridRaw: public FloatVolGrid
{
	int m_nSize[3];
	bool m_bValid;
	float * m_pData;
	inline int GetIdx(int nX, int nY, int nZ) const { return nX + m_nSize[0]*(nY + m_nSize[1]*nZ); }

	double m_lfMin, m_lfMax;

	int m_nNumValidSamples;

	double m_lfMean, m_lfStdDev;
	double m_lfExpSqrd;
	mdsVector<3, double>  EvalGradientAtDataPoint(int nX, int nY, int nZ) const;

public:
	FloatVolGridRaw(void);
	~FloatVolGridRaw(void);

	inline double GetMin() const { return m_lfMin; }
	inline double GetMax() const { return m_lfMax; }

	inline double GetMean() const { return m_lfMean; }
	inline double GetStdDev() const { return m_lfStdDev; }
	inline double GetMeanSqrd() const { return m_lfExpSqrd; } // returns the mean of the squares, not the square of the mean

	virtual double FvgGetMin() const { return GetMin(); }
	virtual double FvgGetMax() const { return GetMax(); }

	virtual double FvgGetMean() const { return GetMean(); }
	virtual double FvgGetStdDev() const { return GetStdDev(); }
	virtual double FvgGetMeanSqrd() const { return GetMeanSqrd(); }

	inline int GetNumValidSamples() const { return m_nNumValidSamples; }

	bool ConvertFromRawVolGrid(const RawVolGrid & rawVolGrid, bool bIsBigEndian);

	virtual int GetDataBounds(int) const;
	virtual mdsVector<2, double> GetSpaceBounds(int) const;
	virtual float GetValAt(int, int, int) const;
	virtual float GetValAt(double, double, double) const;
	virtual void SetValAt(int, int, int, float);
	virtual mdsVector<3, double> EvalGradientAt(double, double, double) const;
};


class FloatVolGridDownSampled: public FloatVolGrid
{
	int m_nSize[3];
	bool m_bValid;
	float * m_pData;
	inline int GetIdx(int nX, int nY, int nZ) const { return nX + m_nSize[0]*(nY + m_nSize[1]*nZ); }

	double m_lfMin, m_lfMax;

	int m_nNumValidSamples;

	double m_lfMean, m_lfStdDev;
	double m_lfExpSqrd;
	mdsVector<3, double>  EvalGradientAtDataPoint(int nX, int nY, int nZ) const;

public:
	FloatVolGridDownSampled(void);
	~FloatVolGridDownSampled(void);

	inline double GetMin() const { return m_lfMin; }
	inline double GetMax() const { return m_lfMax; }

	inline double GetMean() const { return m_lfMean; }
	inline double GetStdDev() const { return m_lfStdDev; }
	inline double GetMeanSqrd() const { return m_lfExpSqrd; } // returns the mean of the squares, not the square of the mean

	inline int GetNumValidSamples() const { return m_nNumValidSamples; }

	virtual double FvgGetMin() const { return GetMin(); }
	virtual double FvgGetMax() const { return GetMax(); }

	virtual double FvgGetMean() const { return GetMean(); }
	virtual double FvgGetStdDev() const { return GetStdDev(); }
	virtual double FvgGetMeanSqrd() const { return GetMeanSqrd(); }

	bool ConvertFromRawVolGrid(const RawVolGrid & rawVolGrid, bool bIsBigEndian);

	bool LoadFromPreprocessedFile(const char * fName, int nX, int nY, int nZ);

	bool DumpToPreprocessedFile(const char * fName) const;

	virtual int GetDataBounds(int) const;
	virtual mdsVector<2, double> GetSpaceBounds(int) const;
	virtual float GetValAt(int, int, int) const;
	virtual float GetValAt(double, double, double) const;
	virtual void SetValAt(int, int, int, float);
	virtual mdsVector<3, double> EvalGradientAt(double, double, double) const;
};

#include "viewInfo.h"

class VolumeViz : public ICustomDraw
{
	FloatVolGrid * m_pVolGrid;
	int m_nRenderMode;
	int m_nStepSize[3];
	double m_lfStdDev;
	double m_lfMean;

	double m_lfTransferOffset;
	double m_lfTransferWidthScale;

	static viewInfo m_gDummyViewInfo;

	viewInfo * m_pViewInfo;

	void GetVolStats()
	{
		m_lfStdDev = m_pVolGrid->FvgGetStdDev();
		m_lfMean = m_pVolGrid->FvgGetMean();
	}
public:
	VolumeViz();
	VolumeViz(FloatVolGrid & volGrid);
	~VolumeViz();

	void SetVolGrid(FloatVolGrid & volGrid) { m_pVolGrid = &volGrid; GetVolStats(); }

	void SetViewInfo(viewInfo & setTo) { m_pViewInfo = &setTo; }

	// ICustomDraw implementation
	virtual void Draw();
};

#endif